package cn.seaboot.excel.tools;

import cn.seaboot.excel.ExcelBook;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Excel 水印工具
 *
 * @author Mr.css
 * @version 2025-03-26 11:09
 */
public class WatermarkTools extends Tools {

    public WatermarkTools(ExcelBook book) {
        super(book);
    }

    /**
     * 添加水印
     * <p>
     * 要求当前实例必须是{@link XSSFWorkbook}
     *
     * @param bytes  图片 byte 数据
     * @param format E.G.: Workbook.PICTURE_TYPE_PNG
     * @throws IllegalArgumentException 作业空间无法转换为 {@link XSSFWorkbook}
     * @see Workbook
     * @since Excel 2007
     */
    public void watermark(byte[] bytes, int format) {
        XSSFWorkbook wb = book.getXSSFWorkbook();
        XSSFSheet st = wb.getSheet(book.getSheet().getSheetName());

        // add picture
        int pictureIdx = wb.addPicture(bytes, format);
        markPicture(wb, st, pictureIdx);
    }

    /**
     * 添加水印
     *
     * @param is     输入流
     * @param format E.G.: Workbook.PICTURE_TYPE_PNG
     * @throws IOException add picture failed
     * @see Workbook
     * @since Excel 2007
     */
    public void watermark(InputStream is, int format) throws IOException {
        XSSFWorkbook wb = book.getXSSFWorkbook();
        XSSFSheet st = wb.getSheet(book.getSheet().getSheetName());

        // add picture
        int pictureIdx = wb.addPicture(is, format);
        markPicture(wb, st, pictureIdx);
    }

    /**
     * 添加水印
     * <p>
     * 要求当前实例必须是{@link XSSFWorkbook}
     *
     * @param image      图片
     * @param formatName 图片类型，E.G.: png
     * @throws IOException              数据格式化异常，无法转换为目标类型的图片
     * @throws IllegalArgumentException 作业空间无法转换为 {@link XSSFWorkbook}
     * @since Excel 2007
     */
    public void watermark(BufferedImage image, String formatName) throws IOException {
        // convert to byte array & add picture
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ImageIO.write(image, formatName, bos);

        int format = Workbook.PICTURE_TYPE_PNG;
        if ("jpg".equals(formatName)) {
            format = Workbook.PICTURE_TYPE_JPEG;
        } else if ("jpeg".equals(formatName)) {
            format = Workbook.PICTURE_TYPE_JPEG;
        }
        this.watermark(bos.toByteArray(), format);
    }

    /**
     * 将图片做成水印
     *
     * @param wb         作业空间
     * @param st         工作表
     * @param pictureIdx 图片ID，文件添加到 Excel 之后产生的一个ID
     * @since Excel 2007
     */
    private void markPicture(XSSFWorkbook wb, XSSFSheet st, int pictureIdx) {
        POIXMLDocumentPart poixmlDocumentPart = wb.getAllPictures().get(pictureIdx);

        PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
        String relType = XSSFRelation.IMAGES.getRelation();
        // add relation from sheet to the picture data
        PackageRelationship pr = st.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
        // set background picture to sheet
        st.getCTWorksheet().addNewPicture().setId(pr.getId());
    }
}
